package edu.cornell.cubooks.listener;

import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.security.event.authentication.AuthenticationFailureBadCredentialsEvent;
import org.springframework.security.event.authentication.AuthenticationFailureProviderNotFoundEvent;
import org.springframework.security.event.authentication.AuthenticationFailureServiceExceptionEvent;
import org.springframework.security.event.authentication.AuthenticationSuccessEvent;
import org.springframework.security.userdetails.UserDetailsService;

import edu.cornell.cubooks.dao.UserDao;
import edu.cornell.cubooks.domain.User;

/**
 * Listener which listen for {@link AuthenticationSuccessEvent} and {@link AuthenticationFailureBadCredentialsEvent}.
 * 
 * <p>
 * 	When event {@link AuthenticationSuccessEvent} occurs the last login date is updated to current date. 
 *  When event {@link AuthenticationFailureBadCredentialsEvent} occurs the failed login attempts
 *  are updated for given username.
 * </p>
 * 
 * @author CUBooks Team
 *
 */
public class LoginListener implements ApplicationListener {
	
	private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(LoginListener.class);
	
	private UserDao userDao;
	
	/*
	 * (non-Javadoc)
	 * @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
	 */
	public void onApplicationEvent(ApplicationEvent event) {
		if (event instanceof AuthenticationSuccessEvent) {
			AuthenticationSuccessEvent authenticationSuccessEvent = (AuthenticationSuccessEvent) event;
			User user = (User) authenticationSuccessEvent.getAuthentication().getPrincipal();
			user.setLastLoginAt(user.getCurrentLoginAt());
			user.setCurrentLoginAt(new Date());
			getUserDao().update(user);
			LOG.info("User " + user.getId() + " succesfully logged in at " + user.getCurrentLoginAt());
		}
		if (event instanceof AuthenticationFailureBadCredentialsEvent) {
			AuthenticationFailureBadCredentialsEvent failureEvent = (AuthenticationFailureBadCredentialsEvent) event;
			String username = failureEvent.getAuthentication().getPrincipal().toString();
			getUserDao().updateFailLoginAttepmts(username);
			User user = (User)((UserDetailsService)getUserDao()).loadUserByUsername(username);
			LOG.info("login failure for user " +user.getId()+" at " + new Date());
		}
		if (event instanceof AuthenticationFailureServiceExceptionEvent) {
			AuthenticationFailureServiceExceptionEvent failureEvent = (AuthenticationFailureServiceExceptionEvent) event;
			LOG.info("login failure for non existing user name " + failureEvent.getAuthentication().getPrincipal() + " at " + new Date());
		}
	
	}

	public UserDao getUserDao() {
		return userDao;
	}
	
	@Autowired
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}
}